﻿//*****************************************************************************
//
//  Copyright 2008 IT Cloud Company
//
//  This software is available under the Microsoft Public License.  Please
//  read the license agreement at http://opensource.org/licenses/ms-pl.html
//  before using the software.
//
//  Authors:
//    Don Song (don@itcloud.com)
//
//*****************************************************************************

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.DirectoryServices;
using System.DirectoryServices.ActiveDirectory;

namespace HeadLinx.AD.Common
{
    public static class HeadLinxUtils
    {
        /// <summary>
        /// Tries to get the specified property from an AD DirectoryEntry.
        /// Does NOT throw an exception if it fails, it simply returns null
        /// value.
        /// </summary>
        /// <param name="entry"></param>
        /// <param name="propName"></param>
        /// <returns></returns>
        public static string TryGetProperty(DirectoryEntry entry, string propName)
        {
            if (entry != null)
            {
                if (entry.Properties.Contains(propName))
                {
                    return entry.Properties[propName][0].ToString();
                }
            }

            return null;
        }

        public static string TryGetProperty(SearchResult result, string propName)
        {
            if (result != null)
            {
                if (result.Properties.Contains(propName))
                {
                    return result.Properties[propName][0].ToString();
                }
            }

            return null;
        }

        public static byte[] TryGetByteArrayProperty(DirectoryEntry entry, string propName)
        {
            if (entry != null)
            {
                if (entry.Properties.Contains(propName))
                {
                    object value = entry.Properties[propName][0];
                    return value as System.Byte[];
                }
            }

            return null;
        }

        public static byte[] TryGetByteArrayProperty(string distinguishedName, string propName)
        {
            try
            {
                using (DirectoryEntry entry = new DirectoryEntry("LDAP://" + distinguishedName))
                {
                    if (entry.Properties.Contains(propName))
                    {
                        object value = entry.Properties[propName][0];
                        return value as System.Byte[];
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("TryGetByteArrayProperty failed: " + ex.Message);
            }

            return null;
        }

        public static byte[] TryGetUserThumbnailPhotoBytes(string distinguishedName, bool useJpegPhoto)
        {
            byte[] photoData = null;

            if (useJpegPhoto)
            {
                // Query jpegPhoto AD attribute introduced in Windows Server 2003.
                photoData = TryGetByteArrayProperty(distinguishedName, ADUserPropertyNames.JPEG_PHOTO);
            }
            else
            {
                // Query thumbnailPhoto AD attribute introduced in Windows 2000 Server.
                // Note: for some reason this attribute contains image data encoded as base64.

                byte[] encodedPhotoData = TryGetByteArrayProperty(distinguishedName, ADUserPropertyNames.THUMBNAIL_PHOTO);

                if (encodedPhotoData != null)
                {
                    char[] b64chars = ASCIIEncoding.ASCII.GetChars(encodedPhotoData);
                    photoData = Convert.FromBase64CharArray(b64chars, 0, b64chars.Length);
                }
            }

            return photoData;
        }

        public static void DumpDirectoryEntryProps(DirectoryEntry entry)
        {
            Console.WriteLine("DirectoryEntry for " + entry.Path);

            foreach (PropertyValueCollection propValues in entry.Properties)
            {
                object value = propValues[0];
                Type valueType = value.GetType();
                string svalue;

                if (propValues.PropertyName == "thumbnailPhoto")
                {
                    //ShowThumbnailPhoto(txtUserNameList.Text, (System.Byte[])value);
                    Console.WriteLine("thumbnailPhoto type: " + valueType.FullName);
                }

                if (valueType.IsArray && valueType == typeof(System.Byte[]))
                {
                    svalue = String.Format("Binary ({0} bytes)", ((System.Byte[])value).Length);
                }
                else
                {
                    svalue = value.ToString();
                }

                Console.WriteLine("\t{0} = {1}", propValues.PropertyName, svalue);
            }
        }

        public static void DumpSearchResults(SearchResult result)
        {
            string[] propNames =
            {
                "givenName", // First name
                "middleName", // Middle name
                "sn", // Last name
                "displayName", // Display
                "mailNickname", // Alias
                "thumbnailPhoto", // Thumbnail photo

                "title", // Title
                "company", // Company
                "department", // Cost Center Name
                "extensionAttribute5", // Cost Center
                "physicalDeliveryOfficeName", // Office 
                "telephoneNumber", // Phone
                "mobile",

                "manager", // Organization --> Manager

                "cn",
                "distinguishedName",
                "mail",
                "wWWHomePage"
            };

            Console.WriteLine("Dump result object: " + result.Path);

            foreach (string propName in propNames)
            {
                if (result.Properties.Contains(propName))
                {
                    string propValue = result.Properties[propName][0].ToString();
                    Console.WriteLine("\t{0} = {1}", propName, propValue);
                }
                else
                {
                    Console.WriteLine("\t{0} = <not found>", propName);
                }
            }

            DumpDirectoryEntryProps(result.GetDirectoryEntry());
        }
    }
}
